package mercurows.bocek;

import mercurows.bocek.entity.BocekArrowEntity;
import net.minecraft.client.Minecraft;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.enchantment.Enchantments;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.AbstractArrowEntity;
import net.minecraft.item.*;
import net.minecraft.stats.Stats;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundCategory;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;

import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.function.Predicate;

@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT)
public class BocekBow extends BowItem {

    public BocekBow() {
        super(new Properties().group(ItemGroup.COMBAT).maxDamage(1145).setNoRepair());
    }

    @Override
    public boolean canApplyAtEnchantingTable(ItemStack stack, Enchantment enchantment) {
        return false;
    }

    @Override
    @ParametersAreNonnullByDefault
    public void onPlayerStoppedUsing(ItemStack stack, World worldIn, LivingEntity entityLiving, int timeLeft) {
        if (entityLiving instanceof PlayerEntity) {
            PlayerEntity playerentity = (PlayerEntity) entityLiving;

            if (worldIn.isRemote) {
                Minecraft.getInstance().getSoundHandler().stop(SoundRegistry.BOW_PULL1.getId(), SoundCategory.PLAYERS);
                Minecraft.getInstance().getSoundHandler().stop(SoundRegistry.BOW_PULL2.getId(), SoundCategory.PLAYERS);
                Minecraft.getInstance().getSoundHandler().stop(SoundRegistry.BOW_PULL3.getId(), SoundCategory.PLAYERS);
                Minecraft.getInstance().getSoundHandler().stop(SoundRegistry.BOW_PULL4.getId(), SoundCategory.PLAYERS);
                Minecraft.getInstance().getSoundHandler().stop(SoundRegistry.BOW_PULL5.getId(), SoundCategory.PLAYERS);
            }
            boolean flag = playerentity.abilities.isCreativeMode || EnchantmentHelper.getEnchantmentLevel(Enchantments.INFINITY, stack) > 0;
            ItemStack itemstack = playerentity.findAmmo(stack);

            int i = (int) ((this.getUseDuration(stack) - timeLeft) * 1.43f);
            i = net.minecraftforge.event.ForgeEventFactory.onArrowLoose(stack, worldIn, playerentity, i, !itemstack.isEmpty() || flag);

            if (i < 0) {
                return;
            }

            if (!itemstack.isEmpty() || flag) {
                if (itemstack.isEmpty()) {
                    itemstack = new ItemStack(Items.ARROW);
                }

                float velocity = getArrowVelocity(i);
                if (!((double) velocity < 0.1D)) {
                    boolean flag1 = playerentity.abilities.isCreativeMode || (itemstack.getItem() instanceof ArrowItem && ((ArrowItem) itemstack.getItem()).isInfinite(itemstack, stack, playerentity));
                    if (!worldIn.isRemote) {
                        BocekArrowEntity bocekArrowEntity = new BocekArrowEntity(worldIn, playerentity);

                        bocekArrowEntity.setDirectionAndMovement(playerentity, playerentity.rotationPitch, playerentity.rotationYaw, 0.0F, velocity * 4.5F, 0.0F);

                        bocekArrowEntity.setDamage(20 + 50 * velocity);
                        bocekArrowEntity.setShooter(playerentity);

                        if (velocity == 1.0f) {
                            bocekArrowEntity.setIsCritical(true);
                        }

                        if (flag1 || playerentity.abilities.isCreativeMode && (itemstack.getItem() == Items.SPECTRAL_ARROW || itemstack.getItem() == Items.TIPPED_ARROW)) {
                            bocekArrowEntity.pickupStatus = AbstractArrowEntity.PickupStatus.CREATIVE_ONLY;
                        }

                        worldIn.addEntity(bocekArrowEntity);
                    }

                    switch ((int) (Math.random() * 4)) {
                        case 0:
                            worldIn.playSound(playerentity, playerentity.getPosition(), SoundRegistry.BOW_LOOSE1.get(), SoundCategory.PLAYERS, 0.5f, 1.0F / (random.nextFloat() * 0.4F + 1.2F) + velocity * 0.5F);
                            break;
                        case 1:
                            worldIn.playSound(playerentity, playerentity.getPosition(), SoundRegistry.BOW_LOOSE2.get(), SoundCategory.PLAYERS, 0.5f, 1.0F / (random.nextFloat() * 0.4F + 1.2F) + velocity * 0.5F);
                            break;
                        case 2:
                            worldIn.playSound(playerentity, playerentity.getPosition(), SoundRegistry.BOW_LOOSE3.get(), SoundCategory.PLAYERS, 0.5f, 1.0F / (random.nextFloat() * 0.4F + 1.2F) + velocity * 0.5F);
                            break;
                        case 3:
                            worldIn.playSound(playerentity, playerentity.getPosition(), SoundRegistry.BOW_LOOSE4.get(), SoundCategory.PLAYERS, 0.5f, 1.0F / (random.nextFloat() * 0.4F + 1.2F) + velocity * 0.5F);
                    }

                    if (!flag1 && !playerentity.abilities.isCreativeMode) {
                        itemstack.shrink(1);
                        if (itemstack.isEmpty()) {
                            playerentity.inventory.deleteStack(itemstack);
                        }
                    }

                    playerentity.addStat(Stats.ITEM_USED.get(this));
                }
            }
        }
    }

    public static float getArrowVelocity(int charge) {
        float f = (float) charge / 20.0F;
        f = (f * f + f * 2.0F) / 3.0F;
        if (f > 1.0F) {
            f = 1.0F;
        }

        return f;
    }

    @Override
    @ParametersAreNonnullByDefault
    @Nonnull
    public UseAction getUseAction(ItemStack stack) {
        return UseAction.BOW;
    }

    @Override
    @ParametersAreNonnullByDefault
    @Nonnull
    public ActionResult<ItemStack> onItemRightClick(World worldIn, PlayerEntity playerentity, Hand handIn) {
        ItemStack itemstack = playerentity.getHeldItem(handIn);
        boolean flag = !playerentity.findAmmo(itemstack).isEmpty();

        ActionResult<ItemStack> ret = net.minecraftforge.event.ForgeEventFactory.onArrowNock(itemstack, worldIn, playerentity, handIn, flag);
        if (ret != null) {
            return ret;
        }

        switch ((int) (Math.random() * 5)) {
            case 0:
                worldIn.playSound(playerentity, playerentity.getPosition(), SoundRegistry.BOW_PULL1.get(), SoundCategory.PLAYERS, 0.7f, 1f);
                break;
            case 1:
                worldIn.playSound(playerentity, playerentity.getPosition(), SoundRegistry.BOW_PULL2.get(), SoundCategory.PLAYERS, 0.7f, 1f);
                break;
            case 2:
                worldIn.playSound(playerentity, playerentity.getPosition(), SoundRegistry.BOW_PULL3.get(), SoundCategory.PLAYERS, 0.7f, 1f);
                break;
            case 3:
                worldIn.playSound(playerentity, playerentity.getPosition(), SoundRegistry.BOW_PULL4.get(), SoundCategory.PLAYERS, 0.7f, 1f);
                break;
            case 4:
                worldIn.playSound(playerentity, playerentity.getPosition(), SoundRegistry.BOW_PULL5.get(), SoundCategory.PLAYERS, 0.7f, 1f);
        }

        if (!playerentity.abilities.isCreativeMode && !flag) {
            return ActionResult.resultFail(itemstack);
        } else {
            playerentity.setActiveHand(handIn);
            return ActionResult.resultConsume(itemstack);
        }
    }

    @Nonnull
    public Predicate<ItemStack> getInventoryAmmoPredicate() {
        return ARROWS;
    }

    @Override
    @ParametersAreNonnullByDefault
    public boolean hasEffect(ItemStack stack) {
        return false;
    }

    @SubscribeEvent
    public static void propertyOverrideRegistry(FMLClientSetupEvent event) {
        event.enqueueWork(() -> ItemModelsProperties.registerProperty(
                ItemRegistry.BOCEK_BOW.get(), new ResourceLocation("bocek", "pull"),
                (itemStack, clientWorld, livingEntity) -> {
                    if (livingEntity == null) {
                        return 0.0f;
                    } else {
                        ItemStack stack = livingEntity.getActiveItemStack();
                        return !stack.isEmpty() && itemStack.getItem() instanceof BocekBow ?
                                (stack.getUseDuration() - livingEntity.getItemInUseCount()) * 1.43f / 20.0f : 0.0f;
                    }
                }
        ));
    }
}
